package org.dxy.domain.handler.mbom;

import com.google.common.eventbus.EventBus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dxy.domain.port.IEventRepository;
import org.dxy.domain.handler.CommandHandler;
import org.dxy.domain.command.mbom.ApproveMBOMCommand;
import org.dxy.domain.event.DomainEvent;
import org.dxy.domain.model.aggregate.MBOMAggRoot;
import org.dxy.domain.port.repository.IMBOMRepository;
import org.dxy.types.common.CommandResult;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.ArrayList;
import java.util.List;

/**
 * 审核通过MBOM命令处理器
 * @author dxy
 * @createTime 2025/9/10
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ApproveMBOMCommandHandler implements CommandHandler<ApproveMBOMCommand, Void> {
    
    private final IMBOMRepository IMBOMRepository;
    private final EventBus eventBus;
    private final IEventRepository eventRepository;
    
    @Transactional
    @Override
    public CommandResult<Void> handle(ApproveMBOMCommand command) {
        try {
            log.info("开始处理审核通过MBOM命令: {}", command);
            
            // 1. 获取MBOM聚合根
            MBOMAggRoot mbomAggRoot = IMBOMRepository.findById(command.mbomId());
            if (mbomAggRoot == null) {
                return CommandResult.fail("MBOM不存在");
            }
            
            // 2. 执行审核通过业务逻辑
            mbomAggRoot.approve(command.approveComment());
            
            // 3. 保存聚合根
            IMBOMRepository.save(mbomAggRoot);

            List<DomainEvent> events = mbomAggRoot.getDomainEvents();
            
            // 4. 保存事件到事件存储，获取固定的事件ID列表
            List<Long> eventIds = eventRepository.saveEvents(events);
            
            // 5. 创建事件副本用于发布
            List<DomainEvent> eventsCopy = new ArrayList<>(events);
            
            // 6. 注册事务提交后的事件发布回调
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCommit() {
                    // 使用事务提交前保存的事件副本
                    eventsCopy.forEach(eventBus::post);

                    // 当事件发布成功后，会把这个字段标记为 true
                    eventRepository.markEventsPublished(eventIds);

                    // 7. 清理事件
                    mbomAggRoot.clearDomainEvents();
                }
            });
            
            log.info("MBOM审核通过成功, mbomId={}, command={}", command.mbomId(), command);
            return CommandResult.success(null, "MBOM审核通过");
            
        } catch (Exception e) {
            log.error("MBOM审核通过失败", e);
            return CommandResult.fail(null, "MBOM审核通过异常");
        }
    }
}